package com.a1anwang.okble.client.scan;


import com.a1anwang.okble.common.LogUtils;
import com.a1anwang.okble.permission.PermissionConstants;
import com.a1anwang.okble.permission.PermissionUtils;
import ohos.app.Context;
import ohos.bluetooth.BluetoothHost;
import ohos.bluetooth.BluetoothRemoteDevice;
import ohos.bluetooth.ble.*;
import ohos.bundle.IBundleManager;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by a1anwang.com on 2017/6/26.
 */

public class OKBLEScanManager {
    private static final String TAG = "OKBLE111111";
    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00202, TAG);
    private static final int MsgWhat_stopScan = 0;
    private static final int MsgWhat_startScan = 1;
    private static final int DefaultScanDuration = 10 * 1000;
    private static final int DefaultSleepDuration = 2 * 1000;
    private boolean enableBluetooth = false;
    private ScanCallback centralManagerCallback;
    private BleCentralManager centralManager;

    // 开启扫描返回失败的时候 是否自动调用代码重启手机蓝牙
    private boolean autoRebootBluetoothWhenScanFailed = false;
    private int scanDuration = DefaultScanDuration;
    private int sleepDuration = DefaultSleepDuration;
    private BluetoothHost host;
    private Context context;
    private DeviceScanCallBack deviceScanCallBack;
    private boolean isScanning = false;

    // 创建扫描过滤器
    List<BleScanFilter> filters = new ArrayList<BleScanFilter>();
    EventRunner runner = EventRunner.create(true);
    MyEventHandler handle = new MyEventHandler(runner);

    public boolean isScanning() {
        return isScanning;
    }


    /**
     * 构造函数
     *
     * @param context 上下文
     */
    public OKBLEScanManager(Context context) {
        this.context = context;
        init();
    }

    /**
     * 构造函数
     *
     * @param context         上下文
     * @param enableBluetooth 初始化时候，如果手机蓝牙未打开，则调用打开蓝牙代码
     */
    public OKBLEScanManager(Context context, boolean enableBluetooth) {
        this.context = context;
        this.enableBluetooth = enableBluetooth;
        init();
    }

    /**
     * 关闭手机蓝牙
     */
    public void disableBluetooth() {
        if (host != null) {
            host.disableBt();
        }
    }

    /**
     * 打开手机蓝牙
     */
    public void enableBluetooth() {
        if (host != null) {
            host.enableBt();
        }
    }

    public void setScanCallBack(DeviceScanCallBack scanCallBack) {
        this.deviceScanCallBack = scanCallBack;
    }

    /**
     * isSupportBLE
     *
     * @return boolean
     */
    public boolean isSupportBLE() {
        return true;
    }

    /**
     * setAutoRebootBluetoothWhenScanFailed
     *
     * @param value 值
     */
    public void setAutoRebootBluetoothWhenScanFailed(boolean value) {
        autoRebootBluetoothWhenScanFailed = value;
    }

    private void init() {
        host = BluetoothHost.getDefaultHost(context);
        if (enableBluetooth) {
            if (host.getBtState() != BluetoothHost.STATE_ON) {
                host.enableBt();
            }
        }
    }

    public void setScanDuration(int scanDuration) {
        this.scanDuration = scanDuration;
    }

    public void setSleepDuration(int sleepDuration) {
        this.sleepDuration = sleepDuration;
    }

    /**
     * retrieveBluetoothDeviceWithMac
     *
     * @param mac mac
     * @return BluetoothRemoteDevice
     */
    public BluetoothRemoteDevice retrieveBluetoothDeviceWithMac(String mac) {
        if (host != null) {
            if (BluetoothHost.isValidBluetoothAddr(mac)) {
                return host.getRemoteDev(mac);
            }
        }
        return null;
    }

    /**
     * MyEventHandler
     *
     * @since 2021-06-03
     */
    class MyEventHandler extends EventHandler {
        private MyEventHandler(EventRunner runner) {
            super(runner);
        }

        @Override
        public void processEvent(InnerEvent event) {
            super.processEvent(event);
            if (event == null) {
                return;
            }
            int eventId = event.eventId;
            switch (eventId) {
                case MsgWhat_stopScan:
                    doStopScan();
                    handle.removeEvent(MsgWhat_startScan);
                    handle.sendEvent(MsgWhat_startScan, sleepDuration);
                    break;
                case MsgWhat_startScan:
                    doScan();
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 可连接
     *
     * @return boolean
     */
    public boolean bluetoothIsEnable() {
        return host.getBtState() == BluetoothHost.STATE_ON;
    }

    /**
     * 开始扫描
     */
    public void startScan() {
        if (!isSupportBLE()) {
            if (callback != null) {
                deviceScanCallBack.onFailed(DeviceScanCallBack.SCAN_FAILED_BLE_NOT_SUPPORT);
            }
            return;
        }
        if (!bluetoothIsEnable()) {
            if (callback != null) {
                deviceScanCallBack.onFailed(DeviceScanCallBack.SCAN_FAILED_BLUETOOTH_DISABLE);
            }
            return;
        }
        if (context.verifySelfPermission("ohos.permission.LOCATION") != IBundleManager.PERMISSION_GRANTED
                || context.verifySelfPermission("ohos.permission.LOCATION_IN_BACKGROUND") != IBundleManager.PERMISSION_GRANTED) {
            // 应用未被授予权限
            if (context.canRequestPermission("ohos.permission.LOCATION")) {
                // 是否可以申请弹框授权(首次申请或者用户未选择禁止且不再提示)
                context.requestPermissionsFromUser(
                        new String[]{"ohos.permission.LOCATION"}, 10011);
            } else {
                doScan();
            }
        } else {
            // 权限已被授予
            if (deviceScanCallBack != null) {
                deviceScanCallBack.onStartSuccess();
            }
            doScan();
        }
    }

    // 实现扫描回调
    public class ScanCallback implements BleCentralManagerCallback {
        @Override
        public void scanResultEvent(BleScanResult bleScan) {
            // 对扫描结果进行处理
            if (!isScanning) return;
            if (deviceScanCallBack != null) {
                BluetoothHost bluetoothHost = BluetoothHost.getDefaultHost(context);
                BluetoothRemoteDevice bluetoothRemoteDevice = bluetoothHost.getRemoteDev(bleScan.getPeripheralDevice().getDeviceAddr());
                BLEScanResult bleScanResult = new BLEScanResult(bluetoothRemoteDevice, bleScan.getRawData(), bleScan.getRssi());
                deviceScanCallBack.onBLEDeviceScan(bleScanResult, bleScanResult.getRssi());
            }
        }

        @Override
        public void scanFailedEvent(int resultCode) {
            LogUtils.e(TAG, "Start Scan failed, Code = " + resultCode);
            if (deviceScanCallBack != null) {
                deviceScanCallBack.onFailed(DeviceScanCallBack.SCAN_FAILED_SYSTEM);
            }
            if (autoRebootBluetoothWhenScanFailed) {
                if (host != null) {
                    host.disableBt();
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            while (true) {
                                try {
                                    Thread.sleep(500);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                                // 要等待蓝牙彻底关闭，然后再打开，才能实现重启效果
                                if (host.getBtState() == BluetoothHost.STATE_OFF) {
                                    host.enableBt();
                                    break;
                                }
                            }
                        }
                    }).start();
                }
            }
        }

        @Override
        public void groupScanResultsEvent(List<BleScanResult> list) {
        }
    }

    private void doScan() {
        if (!bluetoothIsEnable()) {
            return;
        }
        isScanning = true;
        if (sleepDuration > 0) {
            handle.removeEvent(MsgWhat_stopScan);
            handle.sendEvent(MsgWhat_stopScan, scanDuration);
        }
        if (centralManager != null && centralManagerCallback != null) {
            centralManager.stopScan();
        }
        if (centralManagerCallback == null) {
            centralManagerCallback = new ScanCallback();
        }
        if (centralManager == null) {
            centralManager = new BleCentralManager(context, centralManagerCallback);
        }
        HiLog.info(LABEL, "aaaaaa startScan");

        // 开始扫描带有过滤器的指定BLE设备
        centralManager.startScan(filters);
    }

    /**
     * 停止扫描
     */
    public void stopScan() {
        isScanning = false;
        doStopScan();
        handle.removeEvent(MsgWhat_stopScan);
    }

    /**
     * 停止
     */
    private void doStopScan() {
        handle.removeEvent(MsgWhat_startScan);
        if (!bluetoothIsEnable()) {
            return;
        }
        if (isSpecialPhone()) {
            if (centralManager != null && centralManagerCallback != null) {
                centralManager.stopScan();
            }
        }
    }

    // rssi信号强度   实现中心设备管理回调
    private BleCentralManagerCallback callback = new BleCentralManagerCallback() {
        @Override
        public void scanResultEvent(BleScanResult bleScan) {
            if (!isScanning) {
                return;
            }
            if (deviceScanCallBack != null) {
                BluetoothHost bluetoothHost = BluetoothHost.getDefaultHost(context);
                BluetoothRemoteDevice bluetoothRemoteDevice = bluetoothHost.
                        getRemoteDev(bleScan.getPeripheralDevice().getDeviceAddr());
                BLEScanResult bleScanResult = new BLEScanResult(bluetoothRemoteDevice,
                        bleScan.getRawData(), bleScan.getRssi());
                deviceScanCallBack.onBLEDeviceScan(bleScanResult, bleScanResult.getRssi());
            }
        }

        @Override
        public void scanFailedEvent(int i) {
        }

        @Override
        public void groupScanResultsEvent(List<BleScanResult> list) {
        }
    };

    /**
     * 是不是需要特殊适配的机型
     *
     * @return 是不是需要特殊适配的机型
     */
    private boolean isSpecialPhone() {
        return true;
    }

    /**
     * 权限
     */
    public void requestLocationPermission() {
        boolean isGranted = true;
        if (isGranted) {
            return;
        }
        PermissionUtils.permission(PermissionConstants.LOCATION).callback(new PermissionUtils.FullCallback() {
            @Override
            public void onGranted(List<String> permissionsGranted) {
            }

            @Override
            public void onDenied(List<String> permissionsDeniedForever, List<String> permissionsDenied) {
            }
        }).request(context);
    }
}
